#include "stdafx.h"
//-------------------------------------------------------------------------------------------------
//DicomFile.cpp  - Dicom Image  file       
//-------------------------------------------------------------------------------------------------
//FreeBSD License
//Copyright 2011 Will Stott All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are
//permitted provided that the following conditions are met:
//
//   1. Redistributions of source code must retain the above copyright notice, this list of
//      conditions and the following disclaimer.
//
//   2. Redistributions in binary form must reproduce the above copyright notice, this list
//      of conditions and the following disclaimer in the documentation and/or other materials
//      provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY Will Stott ``AS IS'' AND ANY EXPRESS OR IMPLIED
//WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Will Stott OR
//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//The views and conclusions contained in the software and documentation are those of the
//authors and should not be interpreted as representing official policies, either expressed
//or implied, of Will Stott.
//
//----Authors--------------------------------------------------------------------------------------
//created by: will.stott@ucl.ac.uk Feb 2011
//
//----Comments-------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------------------

#include <iostream>
#include <fstream>

#include "DicomFile.h"

DicomFile::DicomFile()
{
	_ImageBytes = NULL;
	_pPixelData = NULL;
	_pEndData = NULL;
	_PixelWidth = 0;
	_PixelHeight = 0;
	_DicomRef = L"?";
	_DicomFileLength = -1;
	_errorCode = DicomFile::NoError;
}

DicomFile::~DicomFile()
{
	if (_ImageBytes != NULL)
		free(_ImageBytes);
	if (_pPixelData != NULL)
		delete _pPixelData;
}

const TCHAR *DicomFile::GetErrorMsg()
{
	if ( _errorCode == DicomFile::InvalidDICM )
		return L"invalid header - no DICM found";
	if ( _errorCode == DicomFile::NoError )
		return L"no error found";
	return L"undefined error";
}

bool DicomFile::SetData(const TCHAR *DicomRef, BYTE *pBlobData, long BlobLen)
{
	bool rc = false;

	_DicomRef = DicomRef;
	_DicomFileLength = BlobLen;

	char dicm[5];

	dicm[0] = *(pBlobData + 128);
	dicm[1] = *(pBlobData + 129);
	dicm[2] = *(pBlobData + 130);
	dicm[3] = *(pBlobData + 131);
	dicm[4] = '\0';

	if (std::strcmp(&dicm[0], "DICM") != 0) 
		_errorCode = DicomFile::InvalidDICM;
	else
	{
		if (_ImageBytes != NULL)
			free(_ImageBytes);
		_ImageBytes = (BYTE *) malloc( BlobLen + 2);
		memcpy(_ImageBytes, pBlobData, BlobLen);

		_pEndData = _ImageBytes + BlobLen + 1;
		*_pEndData = '\0';

		BYTE *pData = _ImageBytes + DicomFile::HeaderLen;

		while ( (pData >= _ImageBytes + DicomFile::HeaderLen) && (pData + DicomPart::HeaderMaxLen) <= (_ImageBytes + _DicomFileLength) )
		{
			DicomPart *pPart = new DicomPart(pData);

			pData = pPart->GetLastDataByte() + 1;

////!!!!!!!!!!!!!!!!!!!!!! - implement as Command Pattern so the processing of DicomPart is performed in ArchiveProcApp.cpp
			std::wcout << pPart->GetTagDescription();
			std::wcout << ", type=" << pPart->GetVRName();
			std::wcout << ", len=" << pPart->GetDataLength() << std::endl;
			std::wcout << "  data=[" << pPart->GetDataAsString() << "]" << std::endl;

			if ((pPart->GetDicomGroup().val == 0x0028) && (pPart->GetDicomElement().val ==  0x0010))
			{
				DicomDataUS height;
				height.b[0] = *(pPart->GetFirstDataByte());
				height.b[1] = *(pPart->GetFirstDataByte()+1);
				_PixelHeight = height.val;
			}

			if ((pPart->GetDicomGroup().val == 0x0028) && (pPart->GetDicomElement().val ==  0x0011))
			{
				DicomDataUS width;
				width.b[0] = *(pPart->GetFirstDataByte());
				width.b[1] = *(pPart->GetFirstDataByte()+1);
				_PixelWidth = width.val;
			}

			if ((pPart->GetDicomGroup().val == 0x7FE0) && (pPart->GetDicomElement().val == 0x0010))
			{
				std::wcout << "processing pixel data" << std::endl;
				_pPixelData = pPart;
			}
			else
			{
				delete pPart; //- delete pPart if the callback returns false, otherwise store it
			}
////!!!!!!!!!!!!!!!!!!!!!!

		}
		if (*_pEndData == '\0')
			rc = true;
	}
	return rc;
}

bool DicomFile::SaveAsFile(TCHAR *Directory)
{
	bool rc = false;

	if (_ImageBytes != NULL)
	{
		std::wstring filename(Directory);
		filename += _DicomRef;
		filename += L".dcm";

		std::ofstream dicomfile;
		dicomfile.open (filename, std::ios::out | std::ios::trunc | std::ios::binary); 

		if (dicomfile.is_open()) 
		{ 
			dicomfile.write((const char *)_ImageBytes, _DicomFileLength);
			dicomfile.close();
			rc = true;
		}
	}
	return rc;
}


USBitMap *DicomFile::CreateBitMap()
{
	USBitMap *rc = NULL;

	if (_pPixelData != NULL )
	{
		rc = new USBitMap(_pPixelData, _PixelWidth, _PixelHeight);
		rc->SetDicomRef(_DicomRef.c_str());

		//if creating the BitMap fails, then delete any USBitMap object referenced by rc
	}

	return rc;
}


//-------------------------------------------------------------------------------------------------
//			E N D   O F   F I L E
//-------------------------------------------------------------------------------------------------
